#ifndef _PLAYER_H
#define _PLAYER_H

#include <vector>
#include <functional>
#include "Drawable.h"
#include "Collideable.h"
#include "Entity.h"
#include "AnimationManager.h"
#include "SFML\Audio.hpp"

enum VelocityApplication
{
	VA_NONE = 0,
	VA_MOVEMENT_STATE,
	VA_FLIP_BASED,
	VA_FLIP_BASED_REVERSE
};

class HUDManager;
class EntityManager;
class Ladder;
class ControlState;
class PlayerState;
class Player : public Entity, public Collideable, public Drawable
{
public:
	enum AlphaInterpolation
	{
		ALPHA_I_POSITIVE = 0,
		ALPHA_I_NEGATIVE
	};

	Player(std::shared_ptr<ControlState> controlState, const std::string& id, EntityManager* entityManager, HUDManager* hudManager);
	~Player(void);

	void move();
	void update();
	void draw(RenderManager* renderManager);
	void initialize();
	void clean();

	sf::FloatRect collisionBox(int type = 0);

	const std::shared_ptr<ControlState> getControlState() { return _controlState; }
	AnimationManager& getAnimationMgr() { return _animation; }

	bool _isJumping;
	bool _isWallJumping;
	float _jumpStartPosition;
	
	void applyVelocity(int = VA_MOVEMENT_STATE, float = 0.0f);
	void resetDash(bool = true);
	void dash();
	void setFlipChangeAllow(bool value)					{ _allowFlipChange = value; }
	void setLadder(Ladder* ladder)						{ _ladder = ladder; }
	void sendLadderCheckBelow();
	void takeDamage(int damage);
	void startFlashing();

	const float getJumpLength()				{ return _jumpLength; }
	const float getJumpPower()				{ return _jumpPower; }
	const float getWallJumpLenght()			{ return _wallJumpLength; }
	const float getFlip()					{ return _flip; }
	const float getAirDashLength()			{ return _airDashLength; }
	const float getDashLength()				{ return _dashLength; }
	const float getWallSlideSpeed()			{ return _wallSlideSpeed; }
	const bool canDash()					{ return _canDash; }
	const bool canTakeDamage()				{ return _canTakeDamage; }
	const float getDashMultiplier()			{ return _dashMultiplier; }
	const float getClimbSpeed()				{ return _climbSpeed; }
	const float getSpeed()					{ return _speed; }
	const int getNormalDamage()				{ return _normalDamage; }
	Ladder* getLadder()						{ return _ladder; }

private:
	void changeState(int state);
	void interpolateAlpha(sf::Color& c);

	AnimationManager _animation;
	PlayerState* _playerState;
	std::shared_ptr<ControlState> _controlState;

	sf::Sprite _main;
	sf::Sprite _bullet;
	sf::Sprite _chargedShot;

	sf::Sound _jumpSFX;
	sf::Sound _landSFX;
	sf::Sound _dashSFX;
	sf::Sound _swing01SFX;
	sf::Sound _swing02SFX;
	sf::Sound _swing03SFX;
	sf::Sound _dmgReceiveSFX;

	int _health;
	int _normalDamage;

	float _flip;
	float _dashMultiplier;
	float _jumpLength;
	float _jumpPower;
	float _wallJumpLength;
	float _dashLength;
	float _airDashLength;
	float _wallSlideSpeed;
	float _speed;
	float _climbSpeed;

	bool _canDash;
	bool _allowFlipChange;
	bool _canTakeDamage;
	bool _flashing;

	short _alpha_i;

	sf::Clock _flashTimer;

	Ladder* _ladder;
	EntityManager* _entityManager;
	HUDManager* _hudManager;

	std::vector<std::function<void ()>> _pStateFunc;
};

#endif // _PLAYER_H